package org.apache.skywalking.apm.plugin.kepler.define;

import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;

import static net.bytebuddy.matcher.ElementMatchers.any;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;

/**
 * @author WeiHui-Z
 * @version v1.0.0
 * @date 2019/6/5 22:11
 * @since JDK 1.8
 */
public class DisruptorActivation extends ClassInstanceMethodsEnhancePluginDefine {

	public static final String ANNOTATION_NAME = "com.xiaomaoguai.fcp.pre.kepler.router.annotation.TraceCrossDisruptor";

	private static final String INIT_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.kepler.define.WorkEventConstructInterceptor";

	private static final String CALL_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.kepler.WorkEventInvokeInterceptor";

	private static final String CALL_METHOD_NAME = "onEvent";

	@Override
	protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
		return new ConstructorInterceptPoint[]{
				new ConstructorInterceptPoint() {

					@Override
					public ElementMatcher<MethodDescription> getConstructorMatcher() {
						return any();
					}

					@Override
					public String getConstructorInterceptor() {
						return INIT_METHOD_INTERCEPTOR;
					}
				}
		};
	}

	@Override
	protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
		return new InstanceMethodsInterceptPoint[]{
				new InstanceMethodsInterceptPoint() {

					@Override
					public ElementMatcher<MethodDescription> getMethodsMatcher() {
						return (named(CALL_METHOD_NAME).and(takesArguments(1)));
					}

					@Override
					public String getMethodsInterceptor() {
						return CALL_METHOD_INTERCEPTOR;
					}

					@Override
					public boolean isOverrideArgs() {
						return false;
					}
				}
		};
	}

	@Override
	protected ClassMatch enhanceClass() {
		return byClassAnnotationMatch(new String[]{ANNOTATION_NAME});
	}

}
